home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / applications / misc / pcal-4.5.lha / pcal / pcallang.h < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-16  |  37.2 KB  |  1,074 lines

  1. /*
  2.  * pcallang.h - language-dependent strings (month and day names, option file 
  3.  * keywords, preprocessor tokens, prepositions, etc.):
  4.  *
  5.  * Revision history:
  6.  *
  7.  *    4.5    AWR    12/21/93    removed references to obsolete
  8.  *                    COLOR_MIN, COLOR_MAX (cf. pcaldefs.h)
  9.  *
  10.  *            11/09/93    parameterize maximum length of entries
  11.  *                    in days[] (DAYSIZE)
  12.  *
  13.  *            09/30/93    revise flag descriptions for [-dnt]
  14.  *                    to reflect independent specification
  15.  *                    of font name and point size
  16.  *
  17.  *            07/09/93    revise PostScript comment block
  18.  *
  19.  *        AWR    02/05/93    support -# flag (specify multiple
  20.  *                    copies of each output page)
  21.  *
  22.  *        AWR    02/11/92    scrap moon file message
  23.  *
  24.  *                    add support for predefined holidays
  25.  *
  26.  *    4.4    AWR    01/20/92    support -z flag (specify time zone)
  27.  *
  28.  *        AWR    01/13/92    support optional font size on -d, -t
  29.  *                    move color names here; change
  30.  *                    semantics, messages, etc. for -[bgOG]
  31.  *
  32.  *    4.3    AWR    12/03/91    support -s flag (override default
  33.  *                    shading of dates and fill boxes)
  34.  *
  35.  *        AWR    10/17/91    support -Z flag to generate debugging
  36.  *                    information
  37.  *
  38.  *    4.2    AWR    10/08/91    support -[kK] flags (select position
  39.  *                    of small calendars
  40.  *
  41.  *        AWR    10/03/91    support "note/<n>" (new message only)
  42.  *
  43.  *                    support -S flag (no small calendars)
  44.  *
  45.  *        AWR    10/02/91    support -N flag (user-specified notes
  46.  *                    heading)
  47.  *
  48.  *                    change message for -n to reflect
  49.  *                    optional notes font size
  50.  *
  51.  *        AWR    09/30/91    support "if" (synonym for "ifdef") and
  52.  *                    "elif" in date file
  53.  *
  54.  *        AWR    09/19/91    support -c flag (generate input file
  55.  *                    suitable for use with Un*x "calendar"
  56.  *                    utility and Pcal)
  57.  *
  58.  *                    support "elif" in "if{n}def" block
  59.  *
  60.  *    4.11    AWR    08/20/91    support "nearest" keyword as per
  61.  *                    Andy Fyfe
  62.  *
  63.  *                    changed MIN_ORD_LEN from 3 to 4 (to
  64.  *                    distinguish "even" from "every")
  65.  *
  66.  *                    add ABBR_DAY_LEN and ABBR_MONTH_LEN
  67.  *                    (cf. writefil.c) for length of
  68.  *                    abbreviated day/month names
  69.  *
  70.  *                    document %u and %w formats and number
  71.  *                    following %[+-] (cf. writefil.c)
  72.  *
  73.  *                    add DEF_WHOLE_YEAR (predefined when
  74.  *                    -w flag specified - cf. pcal.c)
  75.  *
  76.  *    4.1    AWR    08/16/91    support -G flag (outlined gray)
  77.  *
  78.  *    4.02    AWR    07/02/91    support -v flag (version number);
  79.  *                    add ordinal_suffix(); add format
  80.  *                    specifiers to help message
  81.  *
  82.  *    4.0    AWR    03/01/91    expand parameter message to explain
  83.  *                    parameter meaning when -w specified
  84.  *
  85.  *        AWR    02/19/91    revise ordinal definitions for
  86.  *                    support of negative ordinals
  87.  *
  88.  *        AWR    02/06/91    add text describing expression syntax
  89.  *
  90.  *        AWR    02/04/91    support "odd" and "even" ordinals
  91.  *
  92.  *        AWR    01/28/91    support -B (blank fill squares) flag
  93.  *                    and -O (outline "gray" dates) flag
  94.  *
  95.  *        AWR    01/16/91    added moon file support (tokens, help
  96.  *                    file text, error messages); define
  97.  *                    note block heading here
  98.  *
  99.  *        AWR    01/07/91    added support for -w (whole year) flag
  100.  *
  101.  */
  102.  
  103. #define ALL    "all"        /* command-line or date file keywords */
  104. #define HOLIDAY    "holiday"
  105.  
  106. /* names of colors used in printing dates (cf. flag_msg[] below) */
  107.  
  108. #define W_BLACK        "black"
  109. #define W_GRAY        "gray"
  110. #define W_OUTLINE    "outline"
  111. #define W_OUTLINE_GRAY    "outline-gray"
  112.  
  113. #define DAYSIZE 20    /* large enough for longest string in days[] below */
  114.  
  115. #ifdef MAIN_MODULE
  116.  
  117. /* must be in same order as color definitions in pcaldefs.h; also see
  118.  * "prtday{}" in pcalinit.ps
  119.  */
  120.  
  121. char *color_names[] = { W_BLACK, W_GRAY, W_OUTLINE, W_OUTLINE_GRAY };
  122.  
  123. char *months[12] = {
  124.     "January", "February", "March", "April", "May", "June",
  125.     "July", "August", "September", "October", "November", "December"
  126.     };
  127.  
  128. /* Must be a 2-D array so address within may be used as an initializer;
  129.  * wildcard names must be in same order as symbolic names in pcaldefs.h
  130.  */
  131. char days[][DAYSIZE] = {
  132.         "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
  133.         "Saturday",         /* weekday names */
  134.     "day", "weekday", "workday", HOLIDAY, "nonweekday", "nonworkday",
  135.     "nonholiday"        /* wildcards */
  136.     };
  137.  
  138. /* preprocessor tokens: token name, token code, dispatch routine; note that
  139.  * substring "if" must follow "ifdef" and "ifndef" for proper matching
  140.  */
  141.  
  142. KWD_F pp_info[] = {
  143.     "define",    PP_DEFINE,    do_define,
  144.     "elif",        PP_ELIF,    do_ifdef,
  145.     "else",        PP_ELSE,    NULL,
  146.     "endif",    PP_ENDIF,    NULL,
  147.     "ifdef",    PP_IFDEF,    do_ifdef,
  148.     "ifndef",    PP_IFNDEF,    do_ifndef,
  149.     "if",        PP_IFDEF,    do_ifdef,    /* "ifdef" synonym */
  150.     "include",    PP_INCLUDE,    NULL,        /* do_include */
  151.     "undef",    PP_UNDEF,    do_undef,
  152.     NULL,        PP_OTHER,    NULL        /* must be last */
  153.     };
  154.  
  155. /* ordinal numbers - e.g. "first Monday in September": ordinal name,
  156.  * ordinal code, ordinal value; note that "all" is parsed as a keyword
  157.  * and (depending on context) may be subsequently treated as an ordinal
  158.  */
  159.  
  160. KWD_O ordinals[] = {
  161.     "first",    ORD_POSNUM,    FIRST,
  162.     "second",    ORD_POSNUM,    SECOND,
  163.     "third",    ORD_POSNUM,    THIRD,
  164.     "fourth",    ORD_POSNUM,    FOURTH,
  165.     "fifth",    ORD_POSNUM,    FIFTH,
  166.     "last",        ORD_NEGNUM,    LAST,
  167.     "odd",        ORD_ODD,    0,
  168.     "even",        ORD_EVEN,    0,
  169.     NULL,        ORD_OTHER,    0        /* must be last */
  170.     };
  171.  
  172. /* predefined holidays: holiday name, definition, and dispatch function.
  173.  * The definition and dispatch function are mutually exclusive; those
  174.  * holidays which can easily be redefined as an equivalent Pcal date
  175.  * are translated in-line by parse_date() using the definition string,
  176.  * while the "hard" ones - e.g., Easter - each use a dedicated dispatch
  177.  * function instead.  (The syntax for Christmas is awkward, but unlike
  178.  * the obvious "12/25" it is independent of American/European date
  179.  * parsing conventions.)
  180.  */
  181.  
  182. KWD_H holidays[] = {
  183.     "Christmas",    "25th day of December",        NULL,
  184.     "Thanksgiving",    "Fourth Thu in November",    NULL,
  185.     "Easter",    NULL,                find_easter,
  186.     "Good_Friday",    "Friday before Easter",        NULL,
  187.     NULL,        NULL,                NULL    /* must be last */
  188.     };
  189.  
  190. /* allowable suffixes for ordinal numbers - these must be in order 0, 1, 2...
  191.  * according to the rules of the target language; cf. ordinal_suffix() below
  192.  */
  193.  
  194. char *ord_suffix[] = { "th", "st", "nd", "rd", NULL };
  195.  
  196. /* prepositions - e.g., "Friday after fourth Thursday in November" */
  197.  
  198. KWD preps[] = {
  199.     "before",    PR_BEFORE,
  200.     "preceding",    PR_BEFORE,
  201.     "on_or_before",    PR_ON_BEFORE,
  202.     "oob",        PR_ON_BEFORE,
  203.     "after",    PR_AFTER,
  204.     "following",    PR_AFTER,
  205.     "on_or_after",    PR_ON_AFTER,
  206.     "ooa",        PR_ON_AFTER,
  207.     "nearest",    PR_NEAREST,
  208.     NULL,        PR_OTHER };    /* must be last */
  209.  
  210. /* other keywords */
  211.  
  212. KWD keywds[] = {
  213.     ALL,         DT_ALL,
  214.     "each",        DT_ALL,
  215.     "every",    DT_ALL,
  216.     "note",        DT_NOTE,
  217.     "opt",        DT_OPT,
  218.     "year",        DT_YEAR,
  219.     NULL,        DT_OTHER };    /* must be last */
  220.  
  221. /* moon phases (for moon file) */
  222.  
  223. KWD phases[] = {
  224.     "new_moon",    MOON_NM,    /* new moon */
  225.     "nm",        MOON_NM,    
  226.     "first_quarter",MOON_1Q,    /* first quarter */    
  227.     "1Q",        MOON_1Q,    
  228.     "FQ",        MOON_1Q,    
  229.     "full_moon",    MOON_FM,    /* full moon */
  230.     "FM",        MOON_FM,    
  231.     "last_quarter",    MOON_3Q,    /* last (third) quarter */
  232.     "LQ",        MOON_3Q,
  233.     "third_quarter",MOON_3Q,
  234.     "3Q",        MOON_3Q,
  235.     NULL,        MOON_OTHER };    /* must be last */
  236.  
  237. /* default notes box header */
  238.  
  239. char default_notes_hdr[] = "Notes";
  240.  
  241. #else
  242. extern char *color_names[];
  243. extern char *months[];
  244. extern char days[][DAYSIZE];
  245. extern KWD_F pp_info[];
  246. extern KWD_H holidays[];
  247. extern KWD preps[];
  248. extern KWD_O ordinals[];
  249. extern char *ord_suffix[];
  250. extern KWD keywds[];
  251. extern KWD phases[];
  252. extern char default_notes_hdr[];
  253. #endif
  254.  
  255. /* minimum size of abbreviations - adjust as appropriate for target language */
  256.  
  257. #define MIN_DAY_LEN    3    /* distinguish "Thursday" from "third" */
  258. #define ABBR_DAY_LEN    3    /* length of abbreviated day names */
  259. #define MIN_MONTH_LEN    3
  260. #define ABBR_MONTH_LEN    3    /* length of abbreviated month names */
  261. #define MIN_PPTOK_LEN    3
  262. #define MIN_PREP_LEN    7    /* distinguish "on_or_before", "on_or_after" */
  263. #define MIN_ORD_LEN    4    /* distinguish "every" from "even" */
  264.  
  265.  
  266. /*
  267.  * Symbolic names for command-line flags.  These may be changed
  268.  * as desired in order to be meaningful in languages other than
  269.  * English.
  270.  */
  271.  
  272. #define F_INITIALIZE    'I'        /* re-initialize program defaults */
  273. #define    F_BLACK_DAY    'b'        /* print day in black */
  274. #define F_GRAY_DAY    'g'        /* print day in gray */
  275. #define F_OUTLINE    'O'        /* draw "gray" dates as outlines */
  276. #define F_OUTLINE_GRAY    'G'        /* outline and fill "gray" dates */
  277.  
  278. #define F_DAY_FONT    'd'        /* select alternate day font */
  279. #define F_NOTES_FONT    'n'        /* select alternate notes font */
  280. #define F_TITLE_FONT    't'        /* select alternate title font */
  281.  
  282. #define F_REMAP_FONT    'r'        /* remap font for 8-bit characters */
  283.  
  284. #define F_EMPTY_CAL    'e'        /* print empty calendar */
  285. #define F_DATE_FILE    'f'        /* select alternate date file */
  286. #define F_OUT_FILE    'o'        /* select alternate output file */
  287.  
  288. #define F_LANDSCAPE    'l'        /* landscape mode */
  289. #define F_PORTRAIT    'p'        /* portrait mode */
  290.  
  291. #define F_HELP        'h'        /* generate full help message */
  292. #define F_USAGE        'u'        /* generate parameter usage message */
  293. #define F_VERSION    'v'        /* generate version ID */
  294.  
  295. #define F_MOON_4    'm'        /* print new/quarter/full moons */
  296. #define F_MOON_ALL    'M'        /* print all moons */
  297.  
  298. #define F_DEFINE    'D'        /* define preprocessor symbol */
  299. #define F_UNDEF        'U'        /* undefine preprocessor symbol */
  300.  
  301. #define F_L_FOOT    'L'        /* define left foot string */
  302. #define F_C_FOOT    'C'        /* define center foot string */
  303. #define F_R_FOOT    'R'        /* define right foot string */
  304.  
  305. #define F_NOTES_HDR    'N'        /* define heading for notes box */
  306.  
  307. #define F_FIRST_DAY    'F'        /* define alternate starting day */
  308.  
  309. #define F_USA_DATES    'A'        /* parse American date format */
  310. #define F_EUR_DATES    'E'        /* parse European date format */
  311.  
  312. #define F_X_TRANS    'X'        /* X-axis transformation */
  313. #define F_Y_TRANS    'Y'        /* Y-axis transformation */
  314. #define F_X_SCALE    'x'        /* X-axis scale factor */
  315. #define F_Y_SCALE    'y'        /* Y-axis scale factor */
  316.  
  317. #define F_JULIAN    'j'        /* print Julian day (day of year) */
  318. #define F_JULIAN_ALL    'J'        /* print Julian day and days left */
  319.  
  320. #define F_WHOLE_YEAR    'w'        /* print whole year per page */
  321.                     /* (cf. W_WYFLAG below) */
  322.  
  323. #define F_BLANK_BOXES    'B'        /* don't fill unused boxes */
  324.  
  325. #define F_NUM_PAGES    '#'        /* print multiple copies of each page */
  326.  
  327. #define F_SC_NONE    'S'        /* suppress small calendars */
  328. #define F_SC_FIRST    'k'        /* prev/next in first two boxes */
  329. #define F_SC_SPLIT    'K'        /* split between first and last boxes */
  330.  
  331. #define F_SHADING    's'        /* define date/fill box shading */
  332.  
  333. #define F_CALENDAR    'c'        /* generate "calendar" utility input */
  334.  
  335. #define F_TIMEZONE    'z'        /* specify time zone for moon phase */
  336.  
  337. /* special "hidden" flag (and subflags) for debug info generation */
  338.  
  339. #define F_DEBUG        'Z'        /* generate debugging information */
  340.  
  341. #define D_DATES        'D'        /* debug dates as read */
  342. #define D_FILE_PATHS    'F'        /* debug date file paths */
  343. #define D_MOON        'M'        /* debug moon phases */
  344. #define D_TEXT        'T'        /* debug dates/text as written */
  345. #define D_OPT        'O'        /* debug option flags */
  346. #define D_PREPROCESSOR    'P'        /* debug "preprocessor" operation */
  347.  
  348. /*
  349.  * Flag usage information - not strictly language-dependent, but here anyway
  350.  * (N.B.: all flags must be represented by an entry in this table!)
  351.  *
  352.  * Flags may appear in any of three places: in environment variable
  353.  * PCAL_OPTS, on the command line, or in "opt" lines in the date file.
  354.  * The command line is actually parsed twice: once before reading the date
  355.  * file to get the flags needed in processing it (-[bcefgkwADEKSU]), and
  356.  * and again after reading the date file to give the user one last chance
  357.  * to override any of the other flags set earlier.  (Note, however, that
  358.  * the only way to turn off -J|-j [Julian dates], -M|-m [moons], -w [whole
  359.  * year], or -G|-O [outline "gray" dates] once selected is to use -I to
  360.  * reinitialize all program defaults.)
  361.  *
  362.  * The table below supplies the following information about each flag:
  363.  *
  364.  *    - Its name (cf. symbolic definitions above)
  365.  *
  366.  *    - Whether or not it can take an (optional) argument
  367.  *
  368.  *    - Which passes parse it - in order, they are: P_CMD0 ("pre-pass" of
  369.  *      command line to find debugging flags), P_ENV (environment variable),
  370.  *      P_CMD1 (first command line pass), P_OPT ("opt" lines in date file), 
  371.  *      and P_CMD2 (second command line pass).
  372.  *
  373.  *      The basic idea here is that some flags need to be in effect prior
  374.  *      to reading the date file (e.g., -E, -A) while the user should
  375.  *      be able to override other flags set in the date file (e.g., -d,
  376.  *      -n, -t) on the command line if desired.  Two flags - F_OUTLINE
  377.  *      and F_OUTLINE_GRAY - are processed in both command-line passes, for
  378.  *      backward compatibility with earlier versions of Pcal (cf. pcal.c).
  379.  */
  380.  
  381. #ifdef MAIN_MODULE
  382.  
  383. FLAG_USAGE flag_tbl[] = {
  384.  
  385. /*    flag name    arg?             passes where parsed    */
  386.  
  387.     F_INITIALIZE,    FALSE,             P_ENV | P_CMD1 | P_OPT | P_CMD2 ,
  388.  
  389.     F_BLACK_DAY,    TRUE,             P_ENV | P_CMD1 | P_OPT          ,
  390.     F_GRAY_DAY,    TRUE,             P_ENV | P_CMD1 | P_OPT          ,
  391.     F_OUTLINE,    TRUE,             P_ENV | P_CMD1 | P_OPT | P_CMD2 ,
  392.     F_OUTLINE_GRAY,    TRUE,             P_ENV | P_CMD1 | P_OPT | P_CMD2 ,
  393.  
  394.     F_DAY_FONT,    TRUE,             P_ENV          | P_OPT | P_CMD2 ,
  395.     F_NOTES_FONT,    TRUE,             P_ENV          | P_OPT | P_CMD2 ,
  396.     F_TITLE_FONT,    TRUE,             P_ENV          | P_OPT | P_CMD2 ,
  397.  
  398.     F_REMAP_FONT,    TRUE,         P_ENV | P_CMD1 | P_OPT          ,
  399.  
  400.     F_EMPTY_CAL,    FALSE,             P_ENV | P_CMD1                  ,
  401.     F_DATE_FILE,    TRUE,             P_ENV | P_CMD1                  ,
  402.     F_OUT_FILE,    TRUE,             P_ENV          | P_OPT | P_CMD2 ,
  403.  
  404.     F_LANDSCAPE,    FALSE,             P_ENV          | P_OPT | P_CMD2 ,
  405.     F_PORTRAIT,    FALSE,             P_ENV          | P_OPT | P_CMD2 ,
  406.  
  407.     F_HELP,        FALSE,                     P_CMD1                  ,
  408.     F_USAGE,    FALSE,                     P_CMD1                  ,
  409.     F_VERSION,    FALSE,                     P_CMD1                  ,
  410.  
  411.     F_MOON_4,    FALSE,             P_ENV          | P_OPT | P_CMD2 ,
  412.     F_MOON_ALL,    FALSE,             P_ENV          | P_OPT | P_CMD2 ,
  413.  
  414.     F_DEFINE,    TRUE,             P_ENV | P_CMD1                  ,
  415.     F_UNDEF,    TRUE,             P_ENV | P_CMD1                  ,
  416.  
  417.     F_L_FOOT,    TRUE,             P_ENV          | P_OPT | P_CMD2 ,
  418.     F_C_FOOT,    TRUE,             P_ENV          | P_OPT | P_CMD2 ,
  419.     F_R_FOOT,    TRUE,             P_ENV          | P_OPT | P_CMD2 ,
  420.  
  421.     F_NOTES_HDR,    TRUE,             P_ENV          | P_OPT | P_CMD2 ,
  422.  
  423.     F_FIRST_DAY,    TRUE,             P_ENV          | P_OPT | P_CMD2 ,
  424.  
  425.     F_USA_DATES,    FALSE,             P_ENV | P_CMD1 | P_OPT          ,
  426.     F_EUR_DATES,    FALSE,             P_ENV | P_CMD1 | P_OPT          ,
  427.  
  428.     F_X_TRANS,    TRUE,             P_ENV          | P_OPT | P_CMD2 ,
  429.     F_Y_TRANS,    TRUE,             P_ENV          | P_OPT | P_CMD2 ,
  430.     F_X_SCALE,    TRUE,             P_ENV          | P_OPT | P_CMD2 ,
  431.     F_Y_SCALE,    TRUE,             P_ENV          | P_OPT | P_CMD2 ,
  432.  
  433.     F_JULIAN,    FALSE,             P_ENV          | P_OPT | P_CMD2 ,
  434.     F_JULIAN_ALL,    FALSE,             P_ENV          | P_OPT | P_CMD2 ,
  435.  
  436.     F_WHOLE_YEAR,    FALSE,             P_ENV | P_CMD1 | P_OPT          ,
  437.  
  438.     F_BLANK_BOXES,    FALSE,             P_ENV          | P_OPT | P_CMD2 ,
  439.  
  440.     F_NUM_PAGES,    TRUE,             P_ENV          | P_OPT | P_CMD2 ,
  441.  
  442.     F_SC_NONE,    FALSE,             P_ENV | P_CMD1 | P_OPT          ,
  443.     F_SC_FIRST,    FALSE,             P_ENV | P_CMD1 | P_OPT          ,
  444.     F_SC_SPLIT,    FALSE,             P_ENV | P_CMD1 | P_OPT          ,
  445.  
  446.     F_SHADING,    TRUE,            P_ENV          | P_OPT | P_CMD2 ,
  447.  
  448.     F_CALENDAR,    FALSE,             P_ENV | P_CMD1                  ,
  449.  
  450.     F_TIMEZONE,    TRUE,            P_ENV          | P_OPT | P_CMD2 ,
  451.  
  452.     F_DEBUG,    TRUE,    P_CMD0 | P_ENV          | P_OPT          ,
  453.  
  454.     '-',        FALSE,             P_ENV | P_CMD1 | P_OPT | P_CMD2 ,
  455.     '\0',        FALSE,             P_ENV | P_CMD1 | P_OPT | P_CMD2        /* must be last */
  456.     };
  457.  
  458. /* subflags for debug info flag F_DEBUG */
  459.  
  460. DEBUG_INFO debug_info[] = {
  461.     D_DATES,    DEBUG_DATES,
  462.     D_FILE_PATHS,    DEBUG_PATHS,
  463.     D_MOON,        DEBUG_MOON,
  464.     D_OPT,        DEBUG_OPTS,
  465.     D_PREPROCESSOR,    DEBUG_PP,
  466.     D_TEXT,        DEBUG_TEXT,
  467.     '\0',        0        /* must be last */
  468.     };
  469.  
  470. #else
  471. extern FLAG_USAGE flag_tbl[];
  472. extern DEBUG_INFO debug_info[];
  473. #endif
  474.  
  475. /*
  476.  * Words used in usage() message - translate as necessary
  477.  */
  478.  
  479. #define W_DEFAULT    "default"        /* translate as required */
  480. #define W_USAGE        "Usage"
  481.  
  482. #define W_FONT_SIZE    "{<FONT>}{/<n>}"    /* names of metavariables */
  483. #define W_DAY        "<DAY>"
  484. #define W_DAY2        "<DAY>{-<DAY>}"
  485. #define W_STRING    "<STRING>"
  486. #define W_FILE        "<FILE>"
  487. #define W_SYMBOL    "<SYMBOL>"
  488. #define W_VALUE        "<VALUE>"
  489. #define W_MAPPING    "<MAPPING>"
  490. #define W_N        "<n>"
  491. #define W_SHADING    "{<d>}{/<f>}"
  492.  
  493. #define W_MM        "MM"            /* abbrev. for month, year */
  494. #define W_YY        "YY"
  495.  
  496. #define W_WYFLAG    "-w"            /* must conform to F_WHOLE_YEAR */
  497.  
  498. /* special flag_msg[] entries for end of option group, etc. */
  499.  
  500. #define END_GROUP    '\n', NULL, NULL, NULL        /* end of option group */
  501. #define END_LIST    '\0', NULL, NULL, NULL        /* end of list */
  502. #define GROUP_DEFAULT    ' ', NULL, " "            /* group default */
  503.  
  504. /*
  505.  * Message strings to be printed by usage() - translate as necessary
  506.  */
  507. #ifdef MAIN_MODULE
  508.  
  509. FLAG_MSG flag_msg[] = {
  510.  
  511. /*    flag name    metasyntax    description                        default */
  512.  
  513.     F_INITIALIZE,    NULL,        "initialize all parameters to program defaults",    NULL,
  514.     END_GROUP,
  515.  
  516.     F_BLACK_DAY,    W_DAY2,        "print weekday(s) in black",                NULL,
  517.     F_GRAY_DAY,    W_DAY2,        "print weekday(s) in gray",                NULL,
  518.     F_OUTLINE,    W_DAY2,        "print weekday(s) as outline",                NULL,
  519.     F_OUTLINE_GRAY,    W_DAY2,        "print weekday(s) as filled outline",            NULL,
  520.     END_GROUP,
  521.  
  522.     F_SHADING,    W_SHADING,    "specify date/fill box shading (or r:g:b values)",        NULL,
  523.     ' ',        NULL,        " ",                            SHADING,
  524.     END_GROUP,
  525.  
  526.     F_DAY_FONT,    W_FONT_SIZE,    "specify alternate date font and optional size <n>",    NULL,
  527.     ' ',        NULL,        " ",                            DATEFONT,
  528.     F_NOTES_FONT,    W_FONT_SIZE,    "specify alternate notes font and optional size <n>",    NULL,
  529.     ' ',        NULL,        " ",                            NOTESFONT,
  530.     F_TITLE_FONT,    W_FONT_SIZE,    "specify alternate title font and optional size <n>",    NULL,
  531.     ' ',        NULL,        " ",                            TITLEFONT,
  532.     END_GROUP,
  533.  
  534.     F_REMAP_FONT,    W_MAPPING,    "remap 8-bit characters (Roman8, Latin1, or none)",    NULL,
  535. #if MAPFONTS == LATIN1
  536.     GROUP_DEFAULT,                                        MAPPING_L,
  537. #else
  538. #if MAPFONTS == ROMAN8    
  539.     GROUP_DEFAULT,                                        MAPPING_R,
  540. #else
  541.     GROUP_DEFAULT,                                        "no mapping",
  542. #endif
  543. #endif
  544.     END_GROUP,
  545.  
  546.     F_EMPTY_CAL,    NULL,        "generate empty calendar (ignore date file)",        NULL,
  547.     END_GROUP,
  548.  
  549.     F_DATE_FILE,    W_FILE,        "specify alternate date file",                DATEFILE,
  550.     END_GROUP,
  551.  
  552. #ifdef DEFAULT_OUTFILE
  553.     F_OUT_FILE,    W_FILE,        "specify alternate output file",            DEFAULT_OUTFILE,
  554. #else
  555.     F_OUT_FILE,    W_FILE,        "specify alternate output file",            "stdout",
  556. #endif
  557.     END_GROUP,
  558.  
  559.     F_LANDSCAPE,    NULL,        "generate landscape-style calendar",            NULL,
  560.     F_PORTRAIT,    NULL,        "generate portrait-style calendar",            NULL,
  561. #if ROTATE == LANDSCAPE
  562.     GROUP_DEFAULT,                                        "landscape",
  563. #else    
  564.     GROUP_DEFAULT,                                        "portrait",
  565. #endif
  566.     END_GROUP,
  567.  
  568.     F_HELP,        NULL,        "print this help message",                NULL,
  569.     F_USAGE,    NULL,        "print parameter usage message",            NULL,
  570.     F_VERSION,    NULL,        "print version information",                NULL,
  571.     END_GROUP,
  572.  
  573.     F_MOON_4,    NULL,        "draw a \"moon\" icon at full/new/quarter moons",        NULL,
  574.     F_MOON_ALL,    NULL,        "draw a \"moon\" icon every day",            NULL,
  575. #if DRAW_MOONS == NO_MOONS
  576.     GROUP_DEFAULT,                                        "no moons",
  577. #else
  578. #if DRAW_MOONS == SOME_MOONS
  579.     GROUP_DEFAULT,                                        "full/new/quarter moons",
  580. #else
  581.     GROUP_DEFAULT,                                        "every day",
  582. #endif
  583. #endif
  584.     END_GROUP,
  585.  
  586.     F_DEFINE,    W_SYMBOL,    "define preprocessor symbol",                NULL,
  587.     F_UNDEF,    W_SYMBOL,    "undefine preprocessor symbol",                NULL,
  588.     END_GROUP,
  589.  
  590.     F_L_FOOT,    W_STRING,    "specify left foot string",                LFOOT,
  591.     F_C_FOOT,    W_STRING,    "specify center foot string",                CFOOT,
  592.     F_R_FOOT,    W_STRING,    "specify right foot string",                RFOOT,
  593.     END_GROUP,
  594.  
  595.     F_NOTES_HDR,    W_STRING,    "specify header for notes box",                default_notes_hdr,
  596.     END_GROUP,
  597.  
  598.     F_FIRST_DAY,    W_DAY,        "specify starting day of week",                days[FIRST_DAY],
  599.     END_GROUP,
  600.  
  601.     F_USA_DATES,    NULL,        "parse American dates (\"mm/dd{/yy}\" and \"month dd\")", NULL,
  602.     F_EUR_DATES,    NULL,        "parse European dates (\"dd/mm{/yy}\" and \"dd month\")", NULL,
  603. #if DATE_STYLE == USA_DATES
  604.     GROUP_DEFAULT,                                        "American",
  605. #else
  606.     GROUP_DEFAULT,                                        "European",
  607. #endif
  608.     END_GROUP,
  609.  
  610.     F_X_TRANS,    W_VALUE,    "specify x-axis translation",                XTVAL,
  611.     F_Y_TRANS,    W_VALUE,    "specify y-axis translation",                YTVAL,
  612.     F_X_SCALE,    W_VALUE,    "specify x-axis scale factor",                XSVAL,
  613.     F_Y_SCALE,    W_VALUE,    "specify y-axis scale factor",                YSVAL,
  614.     END_GROUP,
  615.  
  616.     F_JULIAN,    NULL,        "print Julian day (day of year)",            NULL,
  617.     F_JULIAN_ALL,    NULL,        "print Julian day and days left in year",        NULL,
  618. #if JULIAN_DATES == NO_JULIANS
  619.     GROUP_DEFAULT,                                        "neither",
  620. #else
  621. #if JULIAN_DATES == SOME_JULIANS
  622.     GROUP_DEFAULT,                                        "Julian day",
  623. #else
  624.     GROUP_DEFAULT,                                        "both",
  625. #endif
  626. #endif
  627.     END_GROUP,
  628.  
  629. #if DO_WHOLE_YEAR == FALSE
  630.     F_WHOLE_YEAR,    NULL,        "print whole year (12 consecutive months) per page",    NULL,
  631. #else
  632.     F_WHOLE_YEAR,    NULL,        "print individual months one per page",            NULL,
  633. #endif
  634.     END_GROUP,
  635.  
  636. #if BLANK_BOXES == FALSE
  637.     F_BLANK_BOXES,    NULL,        "leave unused boxes blank",                NULL,
  638. #else
  639.     F_BLANK_BOXES,    NULL,        "shade unused boxes",                    NULL,
  640. #endif
  641.     END_GROUP,
  642.  
  643.     F_NUM_PAGES,    W_N,        "print <n> copies of each output page",            NCOPY,
  644.     END_GROUP,
  645.  
  646.     F_SC_NONE,    NULL,        "suppress generation of small calendars",        NULL,
  647.     F_SC_FIRST,    NULL,        "print small calendars in first two boxes",        NULL,
  648.     F_SC_SPLIT,    NULL,        "print previous month in first box, next in last",    NULL,
  649. #if SMALL_CAL_POS == SC_LAST
  650.     GROUP_DEFAULT,                                        "last two boxes",
  651. #else
  652. #if SMALL_CAL_POS == SC_FIRST
  653.     GROUP_DEFAULT,                                        "first two boxes",
  654. #else
  655. #if SMALL_CAL_POS == SC_SPLIT
  656.     GROUP_DEFAULT,                                        "first/last boxes",
  657. #else
  658.     GROUP_DEFAULT,                                        "suppress small calendars",
  659. #endif
  660. #endif
  661. #endif
  662.     END_GROUP,
  663.  
  664. #if CALENDAR_OUT == FALSE
  665.     F_CALENDAR,    NULL,        "generate input for Un*x calendar(1) utility",        NULL,
  666. #else
  667.     F_CALENDAR,    NULL,        "generate PostScript output to print calendar",        NULL,
  668. #endif
  669.     END_GROUP,
  670.  
  671.     F_TIMEZONE,    W_VALUE,    "specify time zone in hours west of GMT/UTC",        NULL,
  672.     GROUP_DEFAULT,                                        TIMEZONE,
  673.     END_GROUP,
  674.  
  675.     END_LIST            /* must be last */
  676. };
  677.  
  678. #else
  679. extern FLAG_MSG flag_msg[];
  680. #endif
  681.  
  682. /* Numeric parameter descriptions and text */
  683.  
  684. #ifdef MAIN_MODULE
  685.  
  686. #ifdef __STDC__
  687. PARAM_MSG param_msg[] = {
  688.     W_YY,            "generate calendar for year " W_YY " (19" W_YY " if " W_YY " < 100)",
  689.     W_MM " " W_YY,        "generate calendar for month " W_MM " (Jan = 1), year " W_YY,
  690.     W_MM " " W_YY " N",    "generate calendars for N months, starting at " W_MM "/" W_YY,
  691.     "(" W_DEFAULT ")",    "generate calendar for current month and/or year",
  692.     "",            "",
  693.     "if " W_WYFLAG " specified:",    "",
  694.     "",            "",
  695.     W_YY,            "generate calendar for year " W_YY " (19" W_YY " if " W_YY " < 100)",
  696.     W_MM " " W_YY,        "generate calendars for 12 months, starting at " W_MM "/" W_YY,
  697.     W_MM " " W_YY " N",    "generate calendars for N months, starting at " W_MM "/" W_YY,
  698.     "",            "  (N rounded up to next multiple of 12)",
  699.     "(" W_DEFAULT ")",    "generate calendar for current year",
  700.     NULL,        NULL        /* must be last */
  701. };
  702. #else
  703. PARAM_MSG param_msg[] = {
  704.     "YY",        "generate calendar for year YY (19YY if YY < 100)",
  705.     "MM YY",    "generate calendar for month MM (Jan = 1), year YY",
  706.     "MM YY N",    "generate calendars for N months, starting at MM/YY",
  707.     "(default)",    "generate calendar for current month and year",
  708.     "",        "",
  709.     "if -w specified:",    "",
  710.     "",        "",
  711.     "YY",        "generate calendar for year YY (19YY if YY < 100)",
  712.     "MM YY",    "generate calendar for 12 months, starting at MM/YY",
  713.     "MM YY N",    "generate calendars for N months, starting at MM/YY",
  714.     "",        "  (N rounded up to next multiple of 12)",
  715.     "(default)",    "generate calendar for current year",
  716.     NULL,        NULL        /* must be last */
  717. };
  718. #endif
  719. #else
  720. extern PARAM_MSG param_msg[];
  721. #endif
  722.  
  723. #define PARAM_MSGS    3    /* number of above to print in command-line syntax message */
  724.  
  725. #ifdef MAIN_MODULE
  726.  
  727. /* Date file syntax message - lines are copied intact */
  728.  
  729. char *date_msg[] = {
  730.     "",
  731.     "Date file syntax:",
  732.     "",
  733.     "1) Basic Syntax:",
  734.     "",
  735.     "The following rules describe the syntax of date file entries:",
  736.     "",
  737.     "  year <year>",
  738.     "",
  739.     "  opt <options>",
  740.     "",
  741.     "  note{/<number>} <month_spec> <text>",
  742.     "  note{/<number>} <month> <text>",
  743.     "",
  744.     "  if -A flag (American date formats) specified:",
  745.     "    <month_name> <day>{*} {<text>}",
  746.     "    <month><sep><day>{<sep><year>}{*} {<text>}",
  747.     "",
  748.     "  if -E flag (European date formats) specified:",
  749.     "    <day>{<sep>} <month_name>{*} {<text>}",
  750.     "    <day>{<sep>} <month>{<sep>}{*} {<text>}",
  751.     "    <day><sep><month>{<sep><year>}{*} {<text>}",
  752.     "",
  753.     "  <ordinal> <day_name> in <month_spec>{*} {<text>}",
  754.     "  {<ordinal>} <day_name> <prep> <date_spec>",
  755.     "",
  756.     "  <holiday>",
  757.     "",
  758.     "where",
  759.     "",
  760.     "  {x}          means x is optional",
  761.     "",
  762.     "  <date_spec> := any of the above date specs (not year, note, or opt)",
  763.     "  <month_name> := first 3+ characters of name of month, or \"all\"",
  764.     "  <month_spec> := <month_name>, or \"year\"",
  765.     "  <day_name> := first 3+ characters of name of weekday, \"day\",",
  766.     "\t\t\"weekday\", \"workday\", \"holiday\", \"nonweekday\",",
  767.     "\t\t\"nonworkday\", \"nonholiday\", \"new_moon\",",
  768.     "\t\t\"first_quarter\", \"full_moon\", or \"last_quarter\"",
  769.     "  <ordinal> := ordinal number (\"1st\", \"2nd\", etc.), \"first\" .. \"fifth\",",
  770.     "\t\t\"last\", \"even\", \"odd\", or \"all\"",
  771.     "  <prep> := \"before\", \"preceding\", \"after\", \"following\", \"nearest\",",
  772.     "\t\t\"on_or_before\", or \"on_or_after\"",
  773.     "  <holiday> := \"Christmas\", \"Thanksgiving\", etc.",
  774.     "",
  775.     "  <sep> := one or more non-numeric, non-space, non-'*' characters",
  776.     "  <month>, <day>, <year> are the numeric forms",
  777.     "",
  778.     "  <options> := any command-line option except -[cefhuvDU]",
  779.     "",
  780.     "Comments start with '#' (unless escaped by '\\') and run through",
  781.     "end-of-line.",
  782.     "",
  783.     "Holidays may be flagged by specifying '*' as the last character of the",
  784.     "date field(s), e.g. \"10/12* Columbus Day\", \"July 4* Independence",
  785.     "Day\", etc.  Any dates flagged as holidays will be printed in gray, and",
  786.     "any associated text will appear adjacent to the date.",
  787.     "",
  788.     "Note that the numeric date formats (mm/dd{/yy}, dd.mm{.yy}) support an",
  789.     "optional year, which will become the subsequent default year.  The",
  790.     "alphabetic date formats (month dd, dd month) do not support a year",
  791.     "field; the \"year yy\" command is provided to reset the default year.",
  792.     "",
  793.     "European dates may also be specified as \"dd. mm.\" and \"dd. month\" if",
  794.     "desired.",
  795.     "",
  796.     "\"Floating\" days may be specified in the date file as \"first Mon in",
  797.     "Sep\", \"last Mon in May\", \"4th Thu in Nov\", etc.; any word may be used",
  798.     "in place of \"in\".  \"Relative floating\" days (e.g. \"Fri after 4th Thu",
  799.     "in Nov\") are also accepted; they may span month/year bounds.  Pcal",
  800.     "also accepts date specs such as \"all Friday{s} in October\", \"last",
  801.     "Thursday in all\", etc., and produces the expected results; \"each\" and",
  802.     "\"every\" are accepted as synonyms for \"all\".  Negative ordinals are",
  803.     "allowed; \"-2nd\" means \"next to last\".",
  804.     "",
  805.     "\"Floating\" days may also be specified relative to a fixed date:",
  806.     "\"fourth Sunday before 12/25\", etc; note, however, that only positive",
  807.     "ordinals are meaningful in this context.",
  808.     "",
  809.     "The words \"day\", \"weekday\", \"workday\", and \"holiday\" may be used as",
  810.     "wildcards: \"day\" matches any day, \"weekday\" matches any day normally",
  811.     "printed in black, \"workday\" matches any day normally printed in black",
  812.     "and not explicitly flagged as a holiday, and \"holiday\" matches any day",
  813.     "explicitly flagged as a holiday.  \"Nonweekday\", \"nonworkday\", and",
  814.     "\"nonholiday\" are also supported and have the obvious meanings.  Moon",
  815.     "phases may also appear as wildcards; \"nm\" is accepted as a synonym for",
  816.     "\"new_moon\", \"1q\" and \"fq\" for \"first_quarter\", \"fm\" for \"full_moon\",",
  817.     "and \"3q\", \"lq\", and \"third_quarter\" for \"last_quarter\".",
  818.     "",
  819.     "\"Odd\" and \"even\" do not refer to the actual date; instead, \"odd\" means",
  820.     "\"alternate, starting with the first\"; \"even\" means \"alternate,",
  821.     "starting with the second\".  Thus, \"odd Fridays in March\" refers to the",
  822.     "first, third, and (if present) fifth Fridays in March - not to those",
  823.     "Fridays falling on odd dates.",
  824.     "",
  825.     "\"All\" refers to each individual month; \"year\" refers to the year as an",
  826.     "entity.  Thus \"odd Fridays in all\" refers to the first/third/ fifth",
  827.     "Friday of each month, while \"odd Fridays in year\" refers to the first",
  828.     "Friday of January and every other Friday thereafter.",
  829.     "",
  830.     "Additional notes may be propagated to an empty calendar box by the",
  831.     "inclusion of one or more lines of the form \"note{/<number>} <month>",
  832.     "<text>\", where <month> may be numeric or alphabetic; \"note{/<number>}",
  833.     "all <text>\" propagates <text> to each month in the current year.",
  834.     "<number> is an optional positive or negative number specifying the",
  835.     "empty box where the associated text is to be placed: if positive,",
  836.     "Pcal counts forward from the first empty box; if negative, Pcal counts",
  837.     "backward from the last empty box.  Thus, \"note/1 ...\"  places the",
  838.     "associated text in the first empty box, and \"note/-3 ...\"  in the",
  839.     "third-to-last; the default is -1 (last empty box).  (Note that if the",
  840.     "-S option is used, it must be specified either on the command line or",
  841.     "prior to any \"note\" lines in the date file.)",
  842.     "",
  843.     "",
  844.     "2) Format specifiers:",
  845.     "",
  846.     "Pcal also allows format specifiers in the text (and foot strings - cf.",
  847.     "the -L, -C, -R, and -N options); each will be replaced by its",
  848.     "equivalent string as outlined in the table below.  (Most of these are",
  849.     "derived from the strftime() function; %[lnouwMD0+-] are Pcal-specific.)",
  850.     "",
  851.     "\t%a : abbreviated weekday",
  852.     "\t%A : full weekday",
  853.     "\t%b : abbreviated month name",
  854.     "\t%B : full month name",
  855.     "\t%d : day of month (1-31)",
  856.     "\t%j : day of year (1-366)",
  857.     "\t%l : days left in year (0-365)",
  858.     "\t%m : month (1-12)",
  859.     "\t%u : week number (1-54)",
  860.     "\t%U : week number (0-53)",
  861.     "\t%w : week number (1-54)",
  862.     "\t%W : week number (0-53)",
  863.     "\t%y : year w/o century (00-99)",
  864.     "\t%Y : year w/century",
  865.     "\t%% : '%' character",
  866.     "",
  867.     "\t%o : print number as ordinal",
  868.     "\t%0 : print number with leading zeroes",
  869.     "\t%+ : use following month or year",
  870.     "\t%- : use previous month or year",
  871.     "\t%{+N}[DWMY] : adjust date by +N days/weeks/months/years",
  872.     "\t%{-N}[DWMY] : adjust date by -N days/weeks/months/years",
  873.     "",
  874.     "%u considers the week containing 1/1 as week 1 and the following",
  875.     "logical Sunday (the first day of the week as printed; cf. the -F",
  876.     "flag) as the start of week 2; %U considers the first logical Sunday as",
  877.     "the first day of week 1.  %w and %W behave like %u and %U",
  878.     "respectively, but use the first logical Monday instead.  (Note that %w",
  879.     "has a different meaning to strftime().)",
  880.     "",
  881.     "%o prints a number as an ordinal, with the appropriate suffix (\"st\",",
  882.     "\"nd\", \"rd\", or \"th\" in English) appended; for example, \"%od\" prints",
  883.     "the day of the month as \"1st\", \"2nd\", \"3rd\", etc.",
  884.     "",
  885.     "Unlike strftime(), Pcal's default is to print numbers (except %y)",
  886.     "without leading zeroes.  If leading zeroes are desired, the '0' prefix",
  887.     "may be used; for example, \"%0j\" prints the day of year as 001-365.",
  888.     "",
  889.     "%+ and %- direct Pcal to substitute the following/previous month/year",
  890.     "in the following [bBmyY] specifier; for example, \"%+B\" prints the name",
  891.     "of the next month.",
  892.     "",
  893.     "%{[+-]N}[DWMY] do not print anything, but instead adjust the working",
  894.     "date by +-N days (D), weeks (W), months (M), or years (Y); subsequent",
  895.     "format specifiers use the adjusted date instead of the current date.",
  896.     "For example, \"%+1M %B %Y\" adjusts the date forward by one month and",
  897.     "then prints the resulting month and year (\"January 1991\" in December,",
  898.     "1990); \"%-2W %b %d\" adjusts the date backward by two weeks and prints",
  899.     "the resulting month and day (\"Jul 26\" on August 9).",
  900.     "",
  901.     "Such date adjustments are normally cumulative; for example, \"%+1Y%-1D\"",
  902.     "adjusts the date forward by one year and then backward by one day.  If",
  903.     "%D or %M is specified alone (or if N is zero), Pcal restores the",
  904.     "original date.  (Note that %M has a different meaning to strftime().)",
  905.     "",
  906.     "The \"Notes\" box uses the first of the current month as the default",
  907.     "date.  All foot strings use the first of the current month in single-",
  908.     "month mode and the first of the starting month in whole-year mode.",
  909.     "",
  910.     "",
  911.     "3) Preprocessing:",
  912.     "",
  913.     "Simple cpp-like functionality is provided.  The date file may include",
  914.     "the following commands, which work like their cpp counterparts:",
  915.     "",
  916.     "\tdefine <sym>",
  917.     "\tundef <sym>",
  918.     "",
  919.     "\tif{{n}def} <expr>",
  920.     "\t   ...",
  921.     "\t{ elif <expr>",
  922.     "\t   ... }*",
  923.     "\t{ else",
  924.     "\t   ... }",
  925.     "\tendif",
  926.     "",
  927.     "\tinclude{?} <file>",
  928.     "",
  929.     "Note that these do not start with '#', which is reserved as a comment",
  930.     "character.",
  931.     "",
  932.     "<sym> is a symbol name consisting of a letter followed by zero or more",
  933.     "letters, digits, or underscores ('_').  Symbol names are always",
  934.     "treated in a case-insensitive manner.",
  935.     "",
  936.     "<expr> is an expression consisting of symbol names joined by the",
  937.     "logical operators (in order of precedence, high to low) '!'  (unary",
  938.     "negate), '&' (and), '^' (exclusive or), and '|' (inclusive or).  '&&'",
  939.     "and '||' are accepted as synonyms for '&' and '|' respectively; the",
  940.     "order of evaluation may be altered by the use of parentheses.  A",
  941.     "symbol whose name is currently defined evaluates to TRUE; one whose",
  942.     "name is not currently defined evaluates to FALSE.  Thus \"ifdef A | B |",
  943.     "C\" is TRUE if any of the symbols A, B, and C is currently defined, and",
  944.     "\"ifdef A & B & C\" is TRUE if all of them are.",
  945.     "",
  946.     "\"ifndef A | B | C\" is equivalent to \"ifdef !(A | B | C)\" (or, using",
  947.     "DeMorgan's Law, \"ifdef !A & !B & !C\") - in other words, TRUE if none",
  948.     "of the symbols A, B, and C is currently defined.",
  949.     "",
  950.     "\"if\" is accepted as a synonym for \"ifdef\".",
  951.     "",
  952.     "\"elif A\" is TRUE if A is defined.  Multiple \"elif\" clauses may appear;",
  953.     "at most one \"if{{n}def}\", \"elif\", or \"else\" clause in a given block",
  954.     "will be processed.",
  955.     "",
  956.     "\"define\" alone deletes all the current definitions; \"if{def}\" alone is",
  957.     "always false; \"ifndef\" alone is always true.",
  958.     "",
  959.     "The file name in the \"include\" directive may optionally be surrounded",
  960.     "by \"\" or <>; in any case, path names are taken to be relative to the",
  961.     "location of the file containing the \"include\" directive.  If the",
  962.     "string \"%y\" appears in the file name, it is replaced by the last two",
  963.     "digits of the current year.  The alternate form, \"include?\", directs",
  964.     "pcal to silently continue if the specified file cannot be opened. ",
  965.     "",
  966.     "",
  967.     "4) Miscellaneous:",
  968.     "",
  969.     "The \"-w\" flag defines the symbol \"whole_year\", which may be tested in",
  970.     "the same manner as any user-defined symbol.",
  971.     "",
  972.     "Pcal also supports several predefined holidays; type \"pcal -h\" to",
  973.     "generate a list of these.",
  974.     NULL
  975.     };
  976. #else
  977. extern char *date_msg[];
  978. #endif
  979.  
  980. /* format strings for color_msg() - translate as necessary */
  981. #define COLOR_MSG_1    "all days in %s"
  982. #define COLOR_MSG_2    "in %s; others in %s"
  983.  
  984. /* format string for short usage() message */
  985. #define USAGE_MSG    "\"%s -%c\" prints full description of flags, parameters, and file formats\n"
  986.  
  987. /* format strings for comment in PostScript output file */
  988. #define CREATED_MSG    "Generated by"
  989. #define TITLE_MSG    "calendar for"
  990. #define DATEFILE_MSG    " (from %s)"
  991.  
  992. #define LINE_SEP    ".p"        /* text line separator */
  993.  
  994. /* strings used in error messages */
  995. #define ENV_VAR        "environment variable "
  996. #define DATE_FILE    "date file "
  997.  
  998. /* strings for list of predefined holidays (cf. usage()) */
  999. #define PREDEF_MSG_1    \
  1000.     "Pcal predefines the following holidays:"
  1001. #define PREDEF_MSG_2    \
  1002.     "and will automatically calculate the appropriate date for each."
  1003.  
  1004. /* Error and information messages - translate as necessary */
  1005.  
  1006. /* program error messages */
  1007. #define    E_ALLOC_ERR    "%s: calloc() failed - out of memory\n"
  1008. #define    E_FOPEN_ERR    "%s: can't open file %s\n"
  1009. #define    E_ILL_LINE    "%s: %s in file %s, line %d\n"
  1010. #define    E_ILL_MONTH    "%s: month %d not in range %d .. %d\n"
  1011. #define    E_ILL_OPT    "%s: unrecognized flag %s"
  1012. #define E_ILL_OPT2    " (%s\"%s\")"
  1013. #define    E_ILL_YEAR    "%s: year %d not in range %d .. %d\n"
  1014. #define    E_SYMFULL    "%s: symbol table full - can't define %s\n"
  1015. #define    E_UNT_IFDEF    "%s: unterminated if{n}def..{else..}endif in file %s\n"
  1016. #define E_FLAG_IGNORED    "%s: -%c flag ignored (%s\"%s\")\n"
  1017.  
  1018. /* preprocessor error strings */
  1019. #define E_ELSE_ERR    "unmatched \"else\""
  1020. #define E_ELIF_ERR    "unmatched \"elif\""
  1021. #define E_END_ERR    "unmatched \"endif\""
  1022. #define E_GARBAGE    "extraneous data on \"%s\" line"
  1023. #define E_INV_DATE    "invalid date"
  1024. #define E_NO_MATCH    "no match for wildcard"
  1025. #define E_INV_LINE    "unrecognized line"
  1026. #define E_FILE_NESTING    "maximum file nesting level exceeded"
  1027. #define E_IF_NESTING    "maximum \"if{n}def\" nesting level exceeded"
  1028. #define E_EXPR_SYNTAX    "syntax error in expression"
  1029.  
  1030. /* moon file error strings */
  1031. #define E_DATE_SEQ    "date or phase out of sequence"
  1032. #define E_PREM_EOF    "premature EOF"
  1033.  
  1034. /* information message (VMS, Amiga only) */
  1035. #define    I_OUT_NAME    "%s: output is in file %s\n"
  1036.  
  1037. /* predefined macro names */
  1038. #define DEF_WHOLE_YEAR    "whole_year"        /* defined when -w set */
  1039.  
  1040. /*
  1041.  * Yes, some source code in a header file.  This is a language-dependent
  1042.  * routine used by writefil.c to translate the %o (ordinal suffix) format
  1043.  * specifier into the appropriate string for printing, and seemed to belong
  1044.  * here with the other language dependencies.
  1045.  */
  1046. #ifdef WRITEFIL            /* include only in writefil.c */
  1047. #ifdef PROTOS
  1048. static char *ordinal_suffix(int num)
  1049. #else
  1050. static char *ordinal_suffix(num)
  1051.     int num;        /* ordinal number - assumed positive */
  1052. #endif
  1053. {
  1054.     static char buf[10];
  1055.     int tens, units;
  1056.  
  1057.     /* Select suffix according to rules for target language.  In English,
  1058.      * the rules are as follows:
  1059.      *
  1060.      *    tens digit    units digit    suffix
  1061.      *      (any)          0, 4..9     "th"
  1062.      *        1           (any)     "th"
  1063.      *      != 1             1         "st"
  1064.      *      != 1             2         "nd"
  1065.      *      != 1             3         "rd"
  1066.      */
  1067.     tens = (num / 10) % 10;
  1068.     units = num % 10;
  1069.     strcpy(buf, ord_suffix[(units > 3 || tens == 1) ? 0 : units]);
  1070.  
  1071.     return buf;
  1072. }
  1073. #endif
  1074.